/*=============================================================================

  ANALOG IO INTERFACE MODULE

  FILE: HAIO.cpp
  
  DESCRIPTION

    Analog IO Interface Moudle

  Copyright (c) DaeSung Engineering Inc. All rights reserved.

=============================================================================*/
/*=============================================================================

                             EDIT HISTORY

  ---------  -------  -------------------------------------------------------
    when       who     what, where, why
  ---------  -------  -------------------------------------------------------
   08/10/03   nso4th   Initial version

=============================================================================*/

/*=============================================================================
  HEADER INCLUSION
=============================================================================*/
#include <Cust_Target.h>
#include <HAIO.h>

/*=============================================================================
  LOCAL FUNCTION
=============================================================================*/
//DEVICE-CONTROL
static mcxt aoDEV_init(void);
static boolean aoDEV_close(mcxt dev);
static boolean aoDEV_ao(int32 ch, double64 val);
static boolean aoDEV_ao_read(int32 ch, double64 *val);

static dword aioEventCallback(dword dwEvent ,dword wParam, dword lParam, mcxt pUser);

/*=============================================================================
  CLASS
=============================================================================*/
HAIO::HAIO():HDev()
{
	Event_SetCallback(aioEventCallback, this);
}

HAIO::~HAIO()
{
	Close();
}

/* Initialize */
boolean HAIO::Init(void)
{
	//int32			j;
	
	m_pDevList[HDEV_0] = aoDEV_init();

	if(m_pDevList[HDEV_0] == NULL)
	{
		return	FALSE;
	}
	SetCurrentDevice(HDEV_0);

	//---MAKE.INIT(5V)
	/*for(j=HAIO_CH0; j<=HAIO_CH3; j++)
	{
		AO(j, 5.0);
	}*/
	
	return	TRUE;
}

/* Close */
boolean HAIO::Close(void)
{
	if(m_pDevList[HDEV_0] != NULL)
	{
		aoDEV_close(m_pDevList[HDEV_0]);
		SetCurrentDevice(HDEV_0);
	}

	return	TRUE;
}

/* AO */
boolean HAIO::AO(int32 ch, double64 val)
{
	//DBGPRINT("[AO%d] %.1f\n", (ch+1), val);

	return	aoDEV_ao(ch, val);
}

boolean HAIO::AOget(int32 ch, double64 *val)
{
	return	aoDEV_ao_read(ch, val);
}

void HAIO::INIT_IO_STATE(void)
{
}


/*=============================================================================
  DEVICE-CONTROL (EMULATOR)
=============================================================================*/
#ifdef TG_HW_AIODEV_SIMUL

typedef struct
{
	boolean		init;
	double64		outVAL[16];
} EMULAO_s;

static EMULAO_s		gAOdev = {FALSE};

mcxt aoDEV_init(void)
{
	EMULAO_s			*p = &gAOdev;
	
	if(p->init)
	{
		return	(mcxt)p;
	}

	p->init = TRUE;

	return	(mcxt)p;
}

boolean aoDEV_close(mcxt dev)
{
	EMULAO_s			*p = &gAOdev;
	
	if(p->init == FALSE)
		return	TRUE;

	p->init = FALSE;

	return	TRUE;
}

boolean aoDEV_ao(int32 ch, double64 val)
{
	EMULAO_s			*p = &gAOdev;

	if(p->init == FALSE)
		return	FALSE;
	
	p->outVAL[ch] = val;

	return	TRUE;
}

boolean aoDEV_ao_read(int32 ch, double64 *val)
{
	EMULAO_s			*p = &gAOdev;

	if(p->init == FALSE)
		return	FALSE;

	*val = p->outVAL[ch];
	
	return	TRUE;
}

/*=============================================================================
  DEVICE-CONTROL (AXT-AO)
=============================================================================*/
#else

#include "./axt/AXTAIO.h"
#include "./axt/AXTLib.h"

typedef struct
{
	boolean		init;
	
	CRITICAL_SECTION	cs;
} AXTAO_s;


static AXTAO_s		gAOdev = {FALSE};

#define AXTAO_ENTER(dev) { \
	EnterCriticalSection(&(dev->cs)); \
 }

#define AXTAO_LEAVE(dev) { \
	LeaveCriticalSection(&(dev->cs)); \
 }

// SIO-AO4R  - DA 4Ch, 12bit, 1U size
 #define AXT_SIO_AO4RB                   (0xA2)            // A2h(162) : AO 4Ch, 12 bit
 
mcxt aoDEV_init(void)
{
	AXTAO_s			*p = &gAOdev;
	boolean			done = FALSE;
	
	if(p->init)
	{
		return	(mcxt)p;
	}

	if(AxtIsInitialized() == FALSE)
	{
		AxtInitialize(NULL, NULL);
	}
	AxtOpenDeviceAuto(BUSTYPE_PCI);

	if(AxtIsInitialized())
	{
		if(AxtOpenDeviceAuto(BUSTYPE_PCI))
		{
			if(AxtGetBoardCounts() > 0)
			{
				if(InitializeAIO())
				{
					int32		j, cnt;
					UINT16		modID;
					
					cnt = AIOget_module_count();
					for(j=0; j<cnt; j++)
					{
						modID = AIOget_moduleid((INT16)j);
						if(modID == AXT_SIO_AO4RB)
						{
							//AIOget_output_number((INT16)j);
							//AIOget_input_number((INT16)j);
							done = TRUE;
							break;
						}
					}
				}
			}
		}
	}
	if(done == FALSE)
	{
		return	NULL;
	}
	//--Voltage.Range(0~5.0V)
	{
		int32		j;

		for(j=0; j<4; j++)
		{
			AIOset_range_dac((INT16)j, 0.0, 5.0);
		}
	}

	p->init = TRUE;

	return	(mcxt)p;
}

boolean aoDEV_close(mcxt dev)
{
	AXTAO_s			*p = &gAOdev;
	
	if(p->init == FALSE)
		return	TRUE;

	p->init = FALSE;

	return	TRUE;
}

boolean aoDEV_ao(int32 ch, double64 val)
{
	AXTAO_s			*p = &gAOdev;

	if(p->init == FALSE)
		return	FALSE;

AXTAO_ENTER(p);
{
	val = MAX(0.0, val);
	val = MIN(val, 5.0);
	
	AIOwrite_dac((INT16)ch, val);
	p->outVAL[ch] = val;
}
AXTAO_LEAVE(p);

	return	TRUE;
}

boolean aoDEV_ao_read(int32 ch, double64 *val)
{
	AXTAO_s			*p = &gAOdev;

	if(p->init == FALSE)
		return	FALSE;

AXTAO_ENTER(p);
{
	*val = p->outVAL[ch];
}
AXTAO_LEAVE(p);

	return	TRUE;
}
#endif

/*=============================================================================
  EVENT HANDLER
=============================================================================*/
dword HAIO::Event_Handler(dword dwEvent, dword wParam, dword lParam)
{
	if(Event_PreProc(HDEV_GETEVENT(dwEvent), wParam, lParam))
	{
		return	TRUE;
	}

	return	Event_Pass(HDEV_GETEVENT(dwEvent), wParam, lParam);
}

dword HAIO::Event_PreProc(dword dwEvent, dword wParam, dword lParam)
{
	return	FALSE;
}

static dword aioEventCallback(dword dwEvent, dword wParam, dword lParam, mcxt pUser)
{
	HDevCliCxt	*pCxt = (HDevCliCxt*)pUser;

	if(pCxt && pCxt->pThis)
	{
		return pCxt->pThis->Event_Handler(HDEV_SETDEV_ID(dwEvent, pCxt->dwDevID), wParam, lParam);
	}

	return	(0);
}

/*--- END OF HAIO.CPP ---*/
